#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gpiod.h>
#include <alsa/asoundlib.h>
#include <stdbool.h>
#include <signal.h>

#define KEY2_LINE 7 
#define KEY3_LINE 8 
#define GPIO_LINE 9
#define ALSA_PCM_NEW_HW_PARAMS_API

// 音频参数
#define SAMPLE_RATE 44100
#define CHANNELS 2
#define SAMPLE_SIZE 2 // 16-bit
#define BUFFER_SIZE 409600*3 // 缓冲区大小，单位是字节

// 全局变量
static bool keep_running = true;
snd_pcm_t *capture_handle;
bool is_recording = false;
FILE *output_file;

// 信号处理函数
void signal_handler(int signum) {
    keep_running = false;
}

// 获取音频回放通道音量
// card: 声卡名称
// selem: 控制项名称
// 返回值: 当前音量
int get_playback_volume(const char* card, const char* selem) {
    int err;
    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;

    // 打开混音器
    if ((err = snd_mixer_open(&handle, 0)) < 0) {
        fprintf(stderr, "Mixer %s open error: %s\n", card, snd_strerror(err));
        return err;
    }

    // 附加控制接口到混音器
    if ((err = snd_mixer_attach(handle, card)) < 0) {
        fprintf(stderr, "Mixer attach %s error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 注册混音器
    if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
        fprintf(stderr, "Mixer register error: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 加载混音器元素
    if ((err = snd_mixer_load(handle)) < 0) {
        fprintf(stderr, "Mixer %s load error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 分配简单元素ID
    snd_mixer_selem_id_alloca(&sid);

    // 设置简单元素的名称
    snd_mixer_selem_id_set_name(sid, selem);

    // 查找简单元素
    snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);
    if (!elem) {
        fprintf(stderr, "Unable to find simple control '%s',%i\n", selem, 0);
        snd_mixer_close(handle);
        return -ENOENT;
    }

    // 获取回放通道音量
    long volume = 0;
    if ((err = snd_mixer_selem_get_playback_volume(elem, 0, &volume)) < 0) {
        fprintf(stderr, "Unable to get playback volume: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 关闭混音器
    snd_mixer_close(handle);

    return volume; // 成功返回音量
}


// 调整音量的函数
void adjust_volume(long volume_change) {
    long min, max;
    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;
    const char *card = "default";
    const char *selem_name = "PCM";

    snd_mixer_open(&handle, 0);
    snd_mixer_attach(handle, card);
    snd_mixer_selem_register(handle, NULL, NULL);
    snd_mixer_load(handle);

    snd_mixer_selem_id_alloca(&sid);
    snd_mixer_selem_id_set_index(sid, 0);
    snd_mixer_selem_id_set_name(sid, selem_name);
    snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);

    snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
    long volume;
    snd_mixer_selem_get_playback_volume(elem, 0, &volume);

    volume += volume_change;
    if (volume < min) volume = min;
    if (volume > max) volume = max;

    snd_mixer_selem_set_playback_volume_all(elem, volume);

    snd_mixer_close(handle);
}

// 录音函数声明
void start_recording() {
    int rc;
    snd_pcm_hw_params_t *params;
    unsigned int val = SAMPLE_RATE;
    int dir;
    snd_pcm_uframes_t frames;

    // 打开音频设备
    rc = snd_pcm_open(&capture_handle, "hw:0,1", SND_PCM_STREAM_CAPTURE, 0);
    if (rc < 0) {
        fprintf(stderr, "无法打开音频设备: %s\n", snd_strerror(rc));
        return;
    }

    // 分配硬件参数结构体
    snd_pcm_hw_params_alloca(&params);

    // 用默认值填充参数
    snd_pcm_hw_params_any(capture_handle, params);

    // 设置所需的硬件参数
    snd_pcm_hw_params_set_access(capture_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_hw_params_set_format(capture_handle, params, SND_PCM_FORMAT_S16_LE);
    snd_pcm_hw_params_set_channels(capture_handle, params, CHANNELS);
    snd_pcm_hw_params_set_rate_near(capture_handle, params, &val, &dir);

    // 设置周期大小
    frames = 32;
    snd_pcm_hw_params_set_period_size_near(capture_handle, params, &frames, &dir);

    // 设置缓冲区大小
    snd_pcm_uframes_t buffer_size = 4 * frames;
    snd_pcm_hw_params_set_buffer_size_near(capture_handle, params, &buffer_size);

    // 将参数写入设备
    rc = snd_pcm_hw_params(capture_handle, params);
    if (rc < 0) {
        fprintf(stderr, "无法设置参数: %s\n", snd_strerror(rc));
        snd_pcm_close(capture_handle);
        return;
    }

    // 打开输出文件
    output_file = fopen("output.pcm", "wb");
    if (!output_file) {
        fprintf(stderr, "无法打开输出文件\n");
        snd_pcm_close(capture_handle);
        return;
    }

    printf("开始录音...\n");
}

void stop_recording() {
    printf("停止录音...\n");
    if (output_file) {
        fclose(output_file);
    }
    snd_pcm_close(capture_handle);
}

int main() {
    struct gpiod_chip *chip;
    struct gpiod_line *key2_line, *key3_line, *line;
    int key2_value, key3_value, value, last_value, last_key2_value = 1, last_key3_value = 1;  // 初始状态为高电平

    // 设置信号处理
    signal(SIGINT, signal_handler);

    // 打开GPIO芯片
    chip = gpiod_chip_open_by_label("GPIOF");  // 根据您的设备可能需要调整
    if (!chip) {
        perror("打开GPIO芯片失败");
        return 1;
    }

    // 获取GPIO线
    key2_line = gpiod_chip_get_line(chip, KEY2_LINE);
    key3_line = gpiod_chip_get_line(chip, KEY3_LINE);
    line = gpiod_chip_get_line(chip, GPIO_LINE);
    if (!key2_line || !key3_line || !line) {
        perror("获取GPIO线失败");
        gpiod_chip_close(chip);
        return 1;
    }

    // 将GPIO线设置为输入模式
    if (gpiod_line_request_input(key2_line, "key2") < 0 ||
        gpiod_line_request_input(key3_line, "key3") < 0 ||
        gpiod_line_request_input(line, "key1") < 0) {
        perror("请求将GPIO线设置为输入模式失败");
        gpiod_chip_close(chip);
        return 1;
    }

    printf("按键监控启动。按Ctrl+C退出。\n");

    // 获取初始的GPIO线值
    last_value = gpiod_line_get_value(line);

    // 主循环
    while (keep_running) {
        key2_value = gpiod_line_get_value(key2_line);
        key3_value = gpiod_line_get_value(key3_line);
        value = gpiod_line_get_value(line);

        // 检测KEY2
        if (key2_value != last_key2_value && key2_value == 0) {
            printf("当前音量为：%d\n", get_playback_volume("default", "PCM"));
            adjust_volume(5);  // 增加音量
        }

        // 检测KEY3
        if (key3_value != last_key3_value && key3_value == 0) {
            printf("当前音量为：%d\n", get_playback_volume("default", "PCM"));
            adjust_volume(-5);  // 减小音量
        }

        // 检测录音按键
        if (value != last_value) {
            if (value == 0) {
                printf("key pressed\n");
                if (!is_recording) {
                    start_recording();
                    is_recording = true;
                }
            } else {
                printf("key released\n");
                if (is_recording) {
                    stop_recording();
                    is_recording = false;
                }
            }
            last_value = value;
        }

        // 如果正在录音，读取音频数据并保存到文件
        if (is_recording) {
            char buffer[BUFFER_SIZE];
            int frames = snd_pcm_readi(capture_handle, buffer, sizeof(buffer) / (SAMPLE_SIZE * CHANNELS));
            if (frames < 0) {
                frames = snd_pcm_recover(capture_handle, frames, 0);
            }
            if (frames < 0) {
                fprintf(stderr, "录音错误: %s\n", snd_strerror(frames));
            } else {
                fwrite(buffer, SAMPLE_SIZE, frames * CHANNELS, output_file);
            }
        }

        last_key2_value = key2_value;
        last_key3_value = key3_value;

        usleep(50000);  // 50ms延迟，减少CPU使用
    }

    // 清理资源
    gpiod_line_release(key2_line);
    gpiod_line_release(key3_line);
    gpiod_line_release(line);
    gpiod_chip_close(chip);

    printf("程序已终止\n");
    return 0;
}